package com.demo.shiroDemo10.shiro;

import java.util.Set;

import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.demo.shiroDemo10.service.ShiroService;
import com.demo.shiroDemos.model.Operator;

@Component("myRealm")
public class MyRealm extends AuthorizingRealm {

	private static final Logger log = LoggerFactory.getLogger(MyRealm.class);

	@Autowired
	private ShiroService shiroService;

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// null usernames are invalid
		if (principals == null) {
			throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
		}

		String username = (String) getAvailablePrincipal(principals);

		Set<String> roleNames = null;
		Set<String> permissions = null;

		try {
			// Retrieve roles and permissions from database
			roleNames = shiroService.getRolesByUserName(username);
			permissions = shiroService.getPermsByUserNameAndRoles(username, roleNames);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
		info.setStringPermissions(permissions);
		return info;

	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		String username = upToken.getUsername();

		// Null username is invalid
		if (username == null) {
			throw new AccountException("Null usernames are not allowed by this realm.");
		}

		SimpleAuthenticationInfo info = null;
		String password = null;
		
		try {
			Operator operator = shiroService.getOperatorByUsername(username);
			if (operator != null) {
				password = operator.getPassword();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		if (password == null) {
             throw new UnknownAccountException("No account found for user [" + username + "]");
		}
		
		info = new SimpleAuthenticationInfo(username, password.toCharArray(), getName());
		return info;
	}

	@Override
	public Class<?> getAuthenticationTokenClass() {
		return UsernamePasswordToken.class;
	}

	@Override
	public String getName() {
		return MyRealm.class.getSimpleName();
	}

}
